/**
* @file         utils.c
* @author       David Hu (hmd_hubei_cn@163.com)
* @brief
* @version      0.1
* @date         2024.06.30
* @note
* @copyright    Copyright (c) 2022 DAVID HU All rights reserved. Licensed under
the MIT License (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License in the file LICENSE

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.
**/

#include "utils.h"

static union {
  float flo;
  char buf[4];
} HexFloat;

// 16进制转浮点数
float write_hex_to_float(uint32_t number) {
  uint16_t dat0 = number & 0x0000FFFF;
  uint16_t dat1 = (number >> 16) & 0x0000FFFF;
  HexFloat.buf[0] = dat0 & 0xFF;
  HexFloat.buf[1] = (dat0 >> 8) & 0xFF;
  HexFloat.buf[2] = dat1 & 0xFF;
  HexFloat.buf[3] = (dat1 >> 8) & 0xFF;
  float fdata = HexFloat.flo;
  return fdata;
}

// 浮点数转16进制
uint32_t write_float_to_hex(float number) {
  HexFloat.flo = number;
  uint16_t dat0 = (HexFloat.buf[1] << 8) + HexFloat.buf[0];
  uint16_t dat1 = (HexFloat.buf[3] << 8) + HexFloat.buf[2];
  uint32_t ndata = dat0 << 16 | dat1;
  return ndata;
}

// 整数转大端模式的字节数组
void int32_to_byte4(int32_t value, uint8_t *p) {
  p[0] = (uint8_t)((value & 0xff000000) >> 24);
  p[1] = (uint8_t)((value & 0x00ff0000) >> 16);
  p[2] = (uint8_t)((value & 0x0000ff00) >> 8);
  p[3] = (uint8_t)(value & 0x000000ff);
}

// 大端模式的字节数组转整数
int32_t byte4_to_int32(uint8_t *p) {
  return (int32_t)(p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]);
}

// CRC16校验,快速查表
static const uint16_t crc_table[] = {
    0x0000, 0xCC01, 0xD801, 0x1400, 0xF001, 0x3C00, 0x2800, 0xE401,
    0xA001, 0x6C00, 0x7800, 0xB401, 0x5000, 0x9C01, 0x8801, 0x4400};

uint16_t crc16(uint8_t *data, uint32_t len) {
  uint16_t crc = 0xFFFF;
  uint32_t i = 0;
  uint8_t ch = 0;

  for (i = 0; i < len; i++) {
    ch = data[i];
    crc = crc_table[(ch ^ crc) & 15] ^ (crc >> 4);
    crc = crc_table[((ch >> 4) ^ crc) & 15] ^ (crc >> 4);
  }

  return crc;
}

uint16_t modbus_crc16(uint8_t *buf_data, uint16_t buf_len) {
  uint16_t TCPCRC = 0xffff;
  uint16_t POLYNOMIAL = 0xa001;
  uint8_t i, j;

  for (i = 0; i < buf_len; i++) {
    TCPCRC ^= buf_data[i];
    for (j = 0; j < 8; j++) {
      if ((TCPCRC & 0x0001) != 0) {
        TCPCRC >>= 1;
        TCPCRC ^= POLYNOMIAL;
      } else {
        TCPCRC >>= 1;
      }
    }
  }
  return TCPCRC;
}

// 循环队列是一种高效的数据结构，适用于缓冲区和数据流应用，例如串口通信接收缓冲。

// 入队操作
void cb_push(circular_buffer_t *cb, int data) {
  if (cb->count < SIZE) {
    cb->buffer[cb->head] = data;
    cb->head = (cb->head + 1) % SIZE;
    cb->count++;
  }
}

// 出队操作
int cb_pop(circular_buffer_t *cb) {
  if (cb->count > 0) {
    int data = cb->buffer[cb->tail];
    cb->tail = (cb->tail + 1) % SIZE;
    cb->count--;
    return data;
  }
  return -1;  // Buffer is empty
}

// 断言失败处理
void assert_failed(const char *file, int line) {
  printf("Assertion failed at %s:%d\n", file, line);
  // Additional error handling or logging can be added here
}

// 二进制查找
int binary_search(int* arr, int size, int target) {
  int left = 0, right = size - 1;

  while (left <= right) {
    int mid = left + (right - left) / 2;
    if (arr[mid] == target) {
      return mid;
    } else if (arr[mid] < target) {
      left = mid + 1;
    } else {
      right = mid - 1;
    }
  }
  return -1;  // Not found
}

// 固定点数运算（Fixed-Poin Arithmetic）
fixed_t fixed_multiply(fixed_t a, fixed_t b) {
  return (fixed_t)(((int32_t)a * (int32_t)b) >> FIXED_SHIFT);
}


// 字节序转换，大端模式转小端模式
uint16_t big_to_little_endian(uint16_t big_endian) {
  return (big_endian >> 8) | (big_endian << 8);
}

// 字节序转换，小端模式转大端模式
uint16_t little_to_big_endian(uint16_t little_endian) {
  return (little_endian >> 8) | (little_endian << 8);
}

// 位置1
void set_bit(uint32_t *data, uint8_t bit) {
  *data |= (0x1 << bit);
}

// 位置0
void clear_bit(uint32_t *data, uint8_t bit) {
  *data &= ~(0x1 << bit);
}

// 位翻转
void toggle_bit(uint32_t *data, uint8_t bit) {
  *data ^= (0x1 << bit);
}

// 读取位
uint8_t read_bit(uint32_t data, uint8_t bit) {
  return (data >> bit) & 0x1;
}


/********************* (C) COPYRIGHT DAVID HU *******END OF FILE ********/
